﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Globalization;

namespace Dukous.Util
{
    public class TypeConverterUtil
    {
        public static object Convert(object value, Type destinationType)
        {
            return Convert(CultureInfo.CurrentCulture, value, destinationType);
        }

        public static object Convert(CultureInfo culture, object value, Type destinationType)
        {
            if (value == null || destinationType.IsInstanceOfType(value))
            {
                return value;
            }

            return ConvertSimpleType(culture, value, destinationType);
        }

        private static object ConvertSimpleType(CultureInfo culture, object value, Type destinationType)
        {
            if (value == null || destinationType.IsInstanceOfType(value))
            {
                return value;
            }

            // if this is a user-input value but the user didn't type anything, return no value
            string valueAsString = value as string;
            if (valueAsString != null && valueAsString.Trim().Length == 0)
            {
                return null;
            }

            TypeConverter converter = TypeDescriptor.GetConverter(destinationType);
            bool canConvertFrom = converter.CanConvertFrom(value.GetType());
            if (!canConvertFrom)
            {
                converter = TypeDescriptor.GetConverter(value.GetType());
            }
            if (!(canConvertFrom || converter.CanConvertTo(destinationType)))
            {
                string message = String.Format(CultureInfo.CurrentUICulture,
                    "The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.",
                    value.GetType().FullName, destinationType.FullName);
                throw new InvalidOperationException(message);
            }

            try
            {
                object convertedValue = (canConvertFrom) ?
                     converter.ConvertFrom(null /* context */, culture, value) :
                     converter.ConvertTo(null /* context */, culture, value, destinationType);
                return convertedValue;
            }
            catch (Exception ex)
            {
                string message = String.Format(CultureInfo.CurrentUICulture,
                    "The parameter conversion from type '{0}' to type '{1}' failed. See the inner exception for more information.",
                    value.GetType().FullName, destinationType.FullName);
                throw new InvalidOperationException(message, ex);
            }
        }
    }
}
